#ifndef __OWORLD_H__
#define __OWORLD_H__

class oBody;
class oEvent;
class oListener;

class oContactListener: public b2ContactListener
{
	virtual void PostSolve( b2Contact* contact, const b2ContactImpulse* impulse );
	virtual void PreSolve( b2Contact* contact, const b2Manifold* oldManifold );
	virtual void BeginContact( b2Contact* contact );
	virtual void EndContact( b2Contact* contact );
};

class oContactFilter: public b2ContactFilter
{
	virtual bool ShouldCollide( b2Fixture* fixtureA, b2Fixture* fixtureB );
};

class oDLL oWorld: public CCLayer
{
public:
	virtual ~oWorld();
	virtual bool init();
	b2World* getB2World();
	void setIterations(int velocityIter, int positionIter);
	void setGravity(const b2Vec2& gravity);
	b2Vec2 getGravity() const;
	virtual void update(ccTime dt);
	void queryAABB(const b2AABB& aabb, function<void(oBody*)> func);
	void onRefilter(oEvent* e);
	bool isLocked() const;
	LAYER_NODE_FUNC(oWorld);
	static inline float oVal(float value){ return value * b2Factor; }
	static inline b2Vec2 oVal(const b2Vec2& value){ return b2Vec2(value.x * b2Factor, value.y * b2Factor); }
	static inline float b2Val(float value){ return value / b2Factor; }
	static inline b2Vec2 b2Val(const b2Vec2& value){ return b2Vec2(value.x / b2Factor, value.y / b2Factor); }
	static inline b2Vec2 b2Val(const CCPoint& value){ return b2Vec2(value.x / b2Factor, value.y / b2Factor); }
	static float b2Factor;
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
	virtual void onKey(uint8 key, bool isDown);
#endif
protected:
	oWorld();
private:
	b2World _world;
	oContactListener _contactListner;
	oContactFilter _contactFilter;
	int _velocityIterations;
	int _positionIterations;
	oListener* _listener;
};

#endif